/*
 * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
 * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
 * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
 * Vestibulum commodo. Ut rhoncus gravida arcu.
 */

package hello.javaConfig;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import static javafx.scene.input.KeyCode.J;

/**
 * Author hiberk
 * Date 2017/7/17 9:06
 */
@Configuration
@ImportResource(value = "classpath:spring-security.xml")
public class BeanConfig extends WebMvcConfigurerAdapter{

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        return new JedisConnectionFactory();
    }

    @Bean(name="simpleMappingExceptionResolver") //springMVC全局异常配置.boot有自己的异常处理,所以需要其他方式
    public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();

        Properties mappings = new Properties();
        mappings.setProperty("DatabaseException", "error.jsp");
        mappings.setProperty("InvalidCreditCardException", "view");

        r.setExceptionMappings(mappings);  // 默认为空
        r.setDefaultErrorView("view");    // 默认没有
        r.setExceptionAttribute("ex");
//        设置日志输出级别，不定义则默认不输出警告等错误日志信息
        r.setWarnLogCategory("example.MvcLogger");
        return r;
    }

    /**
     * 全局拦截器。配置项目名等信息
     * @return
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new GlobalInterceptor()).addPathPatterns("/**");
        super.addInterceptors(registry);
    }

    class  GlobalInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            request.setAttribute("_PATH", request.getContextPath());

            return true;
        }

        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        }

        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        }
    }


    /**
     * 配置数据源 如果用了默认的application.properties中的boot配置则不需要
     * @return
     */
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.dataSource")
    public DataSource getDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 配置事务管理
      */
    public PlatformTransactionManager platformTransactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    public JdbcOperations jdbcOperations(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Autowired
    private RequestMappingHandlerAdapter handlerAdapter;

    /*class MyWebBindingInitialized implements WebBindingInitializer{
        @Override
        public void initBinder(WebDataBinder binder, WebRequest request) {
            binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
            binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
            binder.registerCustomEditor(Short.class, new CustomNumberEditor(Short.class, true));
            binder.registerCustomEditor(Integer.class, new CustomNumberEditor(Integer.class, true));
            binder.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class, true));
            binder.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, true));
            binder.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, true));
            binder.registerCustomEditor(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
            binder.registerCustomEditor(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));
        }
    }
    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        RequestMappingHandlerAdapter requestMappingHandlerAdapter = new RequestMappingHandlerAdapter();
        requestMappingHandlerAdapter.setCacheSeconds(0);
        requestMappingHandlerAdapter.setWebBindingInitializer(new MyWebBindingInitialized());
        return requestMappingHandlerAdapter;
    }*/

    class StringToDateConverter implements Converter<String, Date> {
        private static final String dateFormat      = "yyyy-MM-dd HH:mm:ss";
        private static final String shortDateFormat = "yyyy-MM-dd";

        /**
         * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
         */
        @Override
        public Date convert(String source) {
            if (source == null || "".equals(source)) {
                return null;
            }
            source = source.trim();
            try {
                if (source.contains("-")) {
                    SimpleDateFormat formatter;
                    if (source.contains(":")) {
                        formatter = new SimpleDateFormat(dateFormat);
                    } else {
                        formatter = new SimpleDateFormat(shortDateFormat);
                    }
                    Date dtDate = formatter.parse(source);
                    return dtDate;
                } else if (source.matches("^\\d+$")) {
                    Long lDate = new Long(source);
                    return new Date(lDate);
                }
            } catch (Exception e) {
                throw new RuntimeException(String.format("parser %s to Date fail", source));
            }
            throw new RuntimeException(String.format("parser %s to Date fail", source));
        }

    }

    @PostConstruct
    public void initEditableValidation() {
        ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) handlerAdapter
                .getWebBindingInitializer();
        if (initializer.getConversionService() != null) {
            GenericConversionService genericConversionService = (GenericConversionService) initializer
                    .getConversionService();
            genericConversionService.addConverter(new StringToDateConverter());
        }
    }
}
